# Pagination

import index from '!!raw-loader!@site/docs/examples/pagination.ex';
import { LiveDemo } from '@site/components/LiveDemo';

In many cases - for example, when working with very large data-sets - we don't want to work with the full collection in memory.
Instead, server-side pagination is used, where the server sends just a single page of data at a time.

Usually, we also want to cache pages that already have been fetched, in order to spare the need for an additional request.

:::info
This feature requires `@ngneat/elf-entities`
:::

Using this feature, you can manage pagination by using the store. First, you need to install the package by using
the CLI command `elf-cli install` and selecting the pagination package, or via npm:

```bash
npm i @ngneat/elf-pagination
```

To use this feature, provide the `withPagination` props factory function in the `createStore` call:

```ts
import { createStore } from '@ngneat/elf';
import { withEntities } from '@ngneat/elf-entities';
import { withPagination } from '@ngneat/elf-pagination';

interface Todo {
  id: number;
  label: string;
}

const todosStore = createStore(
  { name: 'todos' },
  withEntities<Todo>(),
  withPagination(),
);
```

Call `updatePaginationData()` with a configuration object that determines the various pagination settings, and call `setPage()` whenever you want to define the `ids` that belong to a certain page number.

`Note: pagination can start at index 0 or 1.`

```ts title="todos.repository"
import { PaginationData } from '@ngneat/elf-pagination';

export function addTodos(response: PaginationData & { data: Todo[] }) {
  const { data, ...paginationData } = response;

  todosStore.update(
    addEntities(todos),
    updatePaginationData(paginationData),
    setPage(
      1,
      data.map((c) => c.id),
    ),
  );
}
```

In your server calls, you can use the `skipWhilePageExists` operator, which enables you to skip server calls
if the page exists in the store:

```ts
import { skipWhilePageExists } from '@ngneat/elf-pagination';

export function getTodosPage(page: number) {
  return http.get(todosUrl).pipe(
    tap((todos) => addTodos(todos)),
    skipWhilePageExists(page),
  );
}
```

<LiveDemo src={index} packages={['entities', 'pagination']} />

<br />

Additional queries and mutations available are:

## Queries

### `selectCurrentPageEntities`

Select the current page entities:

```ts
import { selectCurrentPageEntities } from '@ngneat/elf-pagination';

todos$ = store.pipe(selectCurrentPageEntities());
```

### `selectCurrentPage`

Select the current page number (by default it's page 1):

```ts
import { selectCurrentPage } from '@ngneat/elf-pagination';

currentPage$ = store.pipe(selectCurrentPage());
```

### `selectHasPage`

Select whether the page exists:

```ts
import { selectHasPage } from '@ngneat/elf-pagination';

hasPage$ = store.pipe(selectHasPage(1));
```

### `hasPage`

Get whether the page exists:

```ts
import { hasPage } from '@ngneat/elf-pagination';

hasPage = store.query(hasPage(1));
```

### `selectPaginationData`

Select the pagination data:

```ts
import { selectPaginationData } from '@ngneat/elf-pagination';

data$ = store.pipe(selectPaginationData());
```

### `getPaginationData`

Get pagination data:

```ts
import { getPaginationData } from '@ngneat/elf-pagination';

data = store.query(getPaginationData());
```

## Mutations

### `setCurrentPage`

Set the current page:

```ts
import { setCurrentPage } from '@ngneat/elf-pagination';

store.update(setCurrentPage(2));
```

### `setPage`

Set the ids belongs to a page:

```ts
import { setPage } from '@ngneat/elf-pagination';

store.update(setPage(2, [id, id, id]));
```

### `updatePaginationData`

Set the current page:

```ts
import { updatePaginationData } from '@ngneat/elf-pagination';

store.update(
  updatePaginationData({
    currentPage: 1,
    perPage: 10,
    total: 96,
    lastPage: 10,
  }),
);
```

### `deletePage`

Delete a page:

```ts
import { deletePage } from '@ngneat/elf-pagination';

store.update(deletePage(2));
```

### `deleteAllPages`

Delete all pages:

```ts
import { deleteAllPages } from '@ngneat/elf-pagination';

store.update(deleteAllPages());
```
